package com.sample.servicefragment;

import android.content.Context;
import android.util.ArrayMap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;

import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelStoreOwner;

import java.util.Iterator;
import java.util.Map;

/**
 * 支持livedata机制的DummyFragment
 */
public abstract class DummyServiceFragment {

    /**
     * 默认构造函数
     */
    public DummyServiceFragment() {

    }

    /**
     * 构造函数
     *
     * @param context 一个 CustomLifecycleService 派生类的对象，是本对象的上下文。
     */
    public <T extends CustomLifecycleService> DummyServiceFragment(@NonNull T context) {
        mBaseService = context;
    }

    /**
     *  被封装的View.
     */
    private View mView = null;

    private boolean isAdded = false;

    /**
     *  被封装的View，添加到windows中时使用的布局参数
     */
    private WindowManager.LayoutParams mLayoutParams = null;

    private WindowManager mWindowManager = null;

    private CustomLifecycleService mBaseService = null;

    private ArrayMap<Observer, LiveData> mObservers = new ArrayMap<>();

    /**
     * 获取上下文的ViewModelStoreOwner对象，CustomLifecycleService 类本身就实现了ViewModelStoreOwner接口
     * @return 上下文 CustomLifecycleService 对象
     */
    public ViewModelStoreOwner getViewModelStoreOwner() {
        return mBaseService;
    }

    /**
     * 获取上下文的LifecycleOwner对象，CustomLifecycleService 类的基类已经实现了LifecycleOwner接口
     * @return 上下文 CustomLifecycleService 对象
     */
    public LifecycleOwner getLifecycleOwner() {
        return mBaseService;
    }

    /**
     * 获取上下文对象
     * @return 上下文 CustomLifecycleService 对象
     */
    public CustomLifecycleService getContext() {
        return mBaseService;
    }

    /**
     * 设置上下文对象
     * @param  context 上下文 CustomLifecycleService 对象
     */
    public void setContext(CustomLifecycleService context) {
        mBaseService = context;
    }

    /**
     * 记录与本类对象相关联的 {@link Observer}对象。
     * 本方法最好在调用 {@link #addView()} 方法之后
     * 再调用。
     */
    void putObserver(Observer observer, LiveData liveData) {
        mObservers.putIfAbsent(observer, liveData);
    }

    /**
     * 移除与本类对象相关联的 {@link Observer}对象。
     */
    void removeObservers() {
        for (Iterator<Map.Entry<Observer, LiveData>> it = mObservers.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<Observer, LiveData> itor = it.next();
            itor.getValue().removeObserver(itor.getKey());
            it.remove();
        }
    }

    /**
     * 创建 LayoutParams 对象，该对象将封装在本类中，在本类封装的 View 对象添加到 Windows 中时使用。
     * @return 所创建的View对象
     */
    public abstract WindowManager.LayoutParams createLayoutParams();

    /**
     * @return 返回封装在本类中的View对象。
     */
    public View getView() {
        return mView;
    }

    /**
     * @return 设置封装在本类中的View对象。
     */
    void setView(View view) {
        mView = view;
    }

    /**
     * @return 返回封装在本类中的 WindowManager.LayoutParams 对象。
     */
    public WindowManager.LayoutParams getLayoutParams() {
        return mLayoutParams;
    }
    /**
     * @return 返回封装在本类中的 WindowManager.LayoutParams 对象。
     */
    public void setLayoutParams(WindowManager.LayoutParams params) {
        mLayoutParams = params;
    }

    /**
     * 将本类封装的View对象添加到 Window 中进行显示。
     * 本方法最好在调用 {@link #putObserver(Observer observer, LiveData liveData)} 方法之后
     * 再调用。
     */
    void addView() {
        if(null == mView) {
            mView = onCreateView();
        }
        if(null == mLayoutParams) {
            mLayoutParams = createLayoutParams();
        }
        if(null == mWindowManager) {
            mWindowManager = (WindowManager) mBaseService.getSystemService(Context.WINDOW_SERVICE);
        }
        Log.d(getContext().getClass().getCanonicalName(), "adding view to the window.");
        mWindowManager.addView(mView, mLayoutParams);
    }

    /**
     * 将本类封装的View对象从 Window 中移除，不再显示。
     * 本方法，也会将与View相关的Observer移除。
     */
    public void removeView() {
        removeObservers();
        if(null != mView) {
            mWindowManager.removeView(mView);
        }
    }

    /**
     * 立即将本类封装的View对象从 Window 中移除，不再显示。
     * 本方法，也会将与View相关的Observer移除。
     */
    public void removeViewImmediate() {
        removeObservers();
        if(null != mView) {
            mWindowManager.removeViewImmediate(mView);
        }
    }

    public void onCreate() {

    }


    // todo 备用
/*    public void setRootViewRes (@LayoutRes int res) {
        mRootViewRes = res;
    }*/

    /**
     * 创建View对象，该对象将被封装在本类中，可以通过{@link  #getView()}访问。
     * @return 所创建的View对象
     */
    public View onCreateView() {
        View view = onCreateView(getContext().getLayoutInflater());
        if(null == view) {
            Log.e(this.getClass().getCanonicalName(), "onCreateView failed, return null.");
        }
        return view;
    }

    public void onDestroy() {
    }

    /**
     * 类似于普通 Fragment，该方法强制由子类完成实现。
     * @param inflater
     * @return
     */
    public abstract View onCreateView(LayoutInflater inflater);


    boolean isAdded() {
        return isAdded;
    }

    void setAdded(boolean added) {
        isAdded = added;
    }
}
